//go:build linux

// nolint: unused

package main

import (
	"encoding/binary"
	"fmt"
	"log"
	"math/rand/v2"
	"net"
	"runtime"
	"sync/atomic"
	"syscall"
)

func FakeV4Main() {
	// ===== 1. 配置参数 =====
	// fakeSrcIP := net.ParseIP("1.1.1.1").To4()
	fakeSrcIP := net.ParseIP("120.230.126.251").To4()
	dstIP := net.ParseIP("36.151.89.61").To4()
	// dstIP := net.ParseIP("172.16.125.57").To4()

	if fakeSrcIP == nil || dstIP == nil {
		log.Fatalf("IP地址格式错误")
	}
	payload := []byte("0:0.0.0.0:1234567890:5000") // UDP负载

	// ===== 2. 创建原始套接字 =====
	if runtime.GOOS != "linux" {
		log.Println("此代码需在Linux运行")
		return
	}
	fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
	if err != nil {
		log.Fatalf("创建原始套接字失败: %v", err)
	}
	defer func(fd int) {
		_ = syscall.Close(fd)
	}(fd)

	var seq atomic.Uint32
	seq.Store(rand.Uint32N(65536))

	// ===== 3. 构造IP头部 =====
	udpLength := uint16(8 + len(payload))
	totalLength := 20 + udpLength
	seqId := uint16(seq.Add(1) % 65536)
	ipHeader := []byte{
		0x45, 0x00, // Version (4) | IHL (5) | TOS (0)
		byte(totalLength >> 8), byte(totalLength), // 总长度 = IP头(20) + UDP头(8) + 负载长度
		byte(seqId >> 8), byte(seqId), // ID标识符(模拟系统自动递增)
		0x40, 0x00, // Flags (DF) | Fragment Offset (0)
		0x40,                // TTL (64)
		syscall.IPPROTO_UDP, // Protocol (UDP)
		0x00, 0x00,          // Checksum (稍后计算)
		0x00, 0x00, 0x00, 0x00, // 源IP (4字节，稍后填写)
		0x00, 0x00, 0x00, 0x00, // 目标IP (4字节，稍后填写)
	}
	// 设置源IP和目的IP
	copy(ipHeader[12:16], fakeSrcIP)
	copy(ipHeader[16:20], dstIP)
	// 计算IP头部校验和
	ipChecksum := calculateChecksum(ipHeader)
	binary.BigEndian.PutUint16(ipHeader[10:12], ipChecksum)

	// ===== 4. 构造UDP头部 =====
	minPort, maxPort := 32768, 60999 // Windows默认范围49152 - 65535
	srcPort := uint16(rand.IntN(maxPort-minPort+1) + minPort)
	targetPort := uint16(17550)
	udpHeader := []byte{
		byte(srcPort >> 8), byte(srcPort), // 源端口
		byte(targetPort >> 8), byte(targetPort), // 目的端口
		byte(udpLength >> 8), byte(udpLength), // UDP头(8) + 负载长度
		0x00, 0x00, // Checksum (稍后计算)
	}

	// ===== 5. 计算UDP校验和 =====
	// 创建伪首部：源IP + 目的IP + 保留 + 协议 + UDP长度
	pseudoHeader := make([]byte, 12)
	copy(pseudoHeader[0:4], fakeSrcIP)
	copy(pseudoHeader[4:8], dstIP)
	pseudoHeader[9] = syscall.IPPROTO_UDP
	binary.BigEndian.PutUint16(pseudoHeader[10:12], udpLength)
	// 组合校验数据：伪首部 + UDP头 + 负载
	checkData := append(pseudoHeader, udpHeader...)
	checkData = append(checkData, payload...)
	// 计算UDP校验和
	udpChecksum := calculateChecksum(checkData)
	binary.BigEndian.PutUint16(udpHeader[6:8], udpChecksum)

	// ===== 6. 组合完整数据包 =====
	packet := make([]byte, 0, totalLength)
	packet = append(packet, ipHeader...)
	packet = append(packet, udpHeader...)
	packet = append(packet, payload...)

	// ===== 7. 发送数据包 =====
	destAddr := syscall.SockaddrInet4{
		Port: 0,
	}
	copy(destAddr.Addr[:], dstIP)
	err = syscall.Sendto(fd, packet, 0, &destAddr)
	if err != nil {
		log.Fatalf("发送失败: %v", err)
	}
	fmt.Println("伪造IP的UDP包发送成功!")
}

func FakeV6Main() {
	// ===== 1. 配置参数 =====
	fakeSrcIP := net.ParseIP("240e:978:1503:4cc:abbe:b911:f0e4:6ccd").To16()
	dstIP := net.ParseIP("fe80::cb10:3f9c:8ef6:f30f").To16()

	if fakeSrcIP == nil || dstIP == nil {
		log.Fatalf("IP地址格式错误")
	}
	payload := []byte("Hello World") // UDP负载

	// ===== 2. 创建原始套接字 =====
	if runtime.GOOS != "linux" {
		log.Println("此代码需在Linux运行")
		return
	}
	fd, err := syscall.Socket(syscall.AF_INET6, syscall.SOCK_RAW, syscall.IPPROTO_RAW)
	if err != nil {
		log.Fatalf("创建原始套接字失败: %v", err)
	}
	defer func(fd int) {
		_ = syscall.Close(fd)
	}(fd)

	// ===== 3. 构造IP头部 =====
	udpLength := uint16(8 + len(payload))
	totalLength := 20 + udpLength
	ipHeader := make([]byte, 40)
	// 版本(6) + 流量类别(0)  [第1字节]
	ipHeader[0] = 0x60 // 0110 0000 (版本6 + 流量类别0)
	// 流标签(0) [第2-4字节]
	binary.BigEndian.PutUint16(ipHeader[1:3], 0)
	// 有效载荷长度 = UDP头(8) + 负载长度 [第5-6字节]
	binary.BigEndian.PutUint16(ipHeader[4:6], udpLength)
	// 下一个头部类型 = UDP(17) [第7字节]
	ipHeader[6] = syscall.IPPROTO_UDP
	// 跳数限制 = 64 [第8字节]
	ipHeader[7] = 64
	copy(ipHeader[8:24], fakeSrcIP)
	copy(ipHeader[24:40], dstIP)

	// ===== 4. 构造UDP头部 =====
	minPort, maxPort := 32768, 60999 // Windows默认范围49152 - 65535
	srcPort := uint16(rand.IntN(maxPort-minPort+1) + minPort)
	targetPort := uint16(16550)
	udpHeader := []byte{
		byte(srcPort >> 8), byte(srcPort), // 源端口
		byte(targetPort >> 8), byte(targetPort), // 目的端口 (稍后填写)
		byte(udpLength >> 8), byte(udpLength), // UDP头(8) + 负载长度
		0x00, 0x00, // Checksum (稍后计算)
	}

	// ===== 5. 计算UDP校验和 =====
	// 创建伪首部：源IP + 目的IP + 保留 + 协议 + UDP长度
	pseudoHeader := make([]byte, 40)
	copy(pseudoHeader[0:16], fakeSrcIP)
	copy(pseudoHeader[16:32], dstIP)
	binary.BigEndian.PutUint32(pseudoHeader[32:36], uint32(len(udpHeader)+len(payload)))
	pseudoHeader[39] = syscall.IPPROTO_UDP
	// 组合校验数据
	checkData := append(pseudoHeader, udpHeader...)
	checkData = append(checkData, payload...)
	// 计算UDP校验和
	udpChecksum := calculateChecksum(checkData)
	binary.BigEndian.PutUint16(udpHeader[6:8], udpChecksum)

	// ===== 6. 组合完整数据包 =====
	packet := make([]byte, 0, totalLength)
	packet = append(packet, ipHeader...)
	packet = append(packet, udpHeader...)
	packet = append(packet, payload...)

	// ===== 7. 发送数据包 =====
	destAddr := syscall.SockaddrInet6{
		Port: 0,
	}
	copy(destAddr.Addr[:], dstIP)
	err = syscall.Sendto(fd, packet, 0, &destAddr)
	if err != nil {
		log.Fatalf("发送失败: %v", err)
	}
	fmt.Println("伪造IP的UDP包发送成功!")
}

func calculateChecksum(data []byte) uint16 {
	var sum uint32

	// 处理每个16位字
	for i := 0; i < len(data); i += 2 {
		var word uint16
		if i+1 < len(data) {
			word = binary.BigEndian.Uint16(data[i : i+2]) // 明确指定2字节范围
		} else {
			word = uint16(data[i]) << 8
		}
		sum += uint32(word)
	}

	// 折叠进位
	for sum > 0xffff {
		sum = (sum >> 16) + (sum & 0xffff)
	}

	// 取反
	return uint16(^sum)
}
